#include <iostream>
#include <future>
#include <functional>
#include <thread>

using namespace std;
using namespace std::chrono;

/**
 * @brief 消费者，等待获取奶茶
 * 获取结果有几种方式：
 * 1）auto value = future.get()，get()方法会阻塞当前线程，等待异步操作结束并返回结果
 * 2）future.wait()，wait()方法也会阻塞，但是不会有返回值
 * 3) std::future_status，判断状态
 * @param future
 */
void waitfor_tea(std::future<int> &future)
{
    std::cout << "wait for milk tea..." << std::endl;

    // 方法1：使用get()
    // auto notice = future.get();

    // 方法2：使用wait()
    // future.wait();
    // auto notice = future.get();

    // 方法3：使用wait_for()，等待特定时间，超时则退出等待
    if (future.wait_for(std::chrono::seconds(2)) == std::future_status::timeout)
    {
        std::cerr << "no tea received, wait too long" << std::endl;
        return;
    }
    auto notice = future.get();
    std::cout << "received tea: " << notice << std::endl;
}

/**
 * @brief 提供者，制作奶茶
 *
 * @param promise
 */
void make_tea(std::promise<int> &promise)
{
    std::cout << "Ready to make tea, please wait!" << std::endl;

    std::this_thread::sleep_for(std::chrono::seconds(3));
    promise.set_value(1); // 设置共享值，相当于奶茶做好了
    std::this_thread::sleep_for(std::chrono::seconds(3));

    std::cout << "MakeTea thread exit!" << std::endl;
}

int main(int argc, char *argv[])
{
    std::promise<int> p_worker;                          // 创建promise，做为一个提供者，用于制作奶茶
    std::future<int> f_customer = p_worker.get_future(); // 创建于promise关联的future， 做为消费者，等待获取奶茶

    std::thread th_worker(make_tea, std::ref(p_worker));
    std::thread th_customer(waitfor_tea, std::ref(f_customer));

    th_worker.join();
    th_customer.join();
    return 0;
}